#ifndef TOOL_MATH_HPP_INCLUDED
#define TOOL_MATH_HPP_INCLUDED

#include <cmath>

namespace shooter
{
namespace tool_math
{
  /** @breif Use a template struct for static const value beacuse hpp file can not have static
             value unless using template. */
  template <int dummy>
  struct basic_parms
  {
    static const double C_Pi2;
    static const double C_Pi;
  };

  template <int dummy>
  const double basic_parms<dummy>::C_Pi2 = std::asin(1);
  template <int dummy>
  const double basic_parms<dummy>::C_Pi = 2 * C_Pi2;

  /**
   * @brief  calculate the magnitude of one edge by its sub edges.
   */
  template <class T>
  T cal_mag(T edge1, T edge2)
  {
    return std::sqrt(edge1*edge1 + edge2*edge2);
  }
  template <class T>
  T cal_mag(T edge1, T edge2, T edge3)
  {
    return std::sqrt(edge1*edge1 + edge2*edge2 + edge3*edge3);
  }

  template <class T>
  T cal_crossProduct(const T & edge1, const T & edge2)
  {
    double x = edge1.y_*edge2.z_ - edge1.z_*edge2.y_;
    double y = edge1.x_*edge2.z_ - edge1.z_*edge2.x_;
    double z = edge1.x_*edge2.y_ - edge1.y_*edge1.z_;
    return T(x, y, z);
  }

  template <class T>
  double cal_dotProduct(const T & edge1, const T & edge2)
  {
    return edge1.x_*edge2.x_ + edge1.z_*edge2.z_ + edge1.y_*edge2.y_;
  }
}

} // namespace shooter


#endif
